﻿/*=========================================================================
 * AUTH: Matthew Baum, 9753095
 * DESC: Game Level Components
 *=========================================================================*/

using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;

namespace RisingThreat
{
    // A floor tile
    class LevelTile
    {
        // Dimension constants
        public static readonly float TILE_WIDTH = 4.0f;
        public static readonly float TILE_HEIGHT = 0.4f;
        public static readonly float TILE_DEPTH = TILE_WIDTH;
        private static readonly Vector3 TILE_DIMENSION_VECTOR = new Vector3(TILE_WIDTH, TILE_HEIGHT, TILE_DEPTH);

        // Color constant
        private static readonly Color TILE_COLOR = Color.Tan;

        // Visual Representation of the tile
        private RectPrism tile;

        /*=================================================================
         * CONSTRUCTORS
         * ----------------------------------------------------------------
         * Parameters:
         * - xOffset: # of tiles away from origin, along the x axis
         * - zOffset: # of tiles away from origin, along the z axis
         *=================================================================*/ 
        public LevelTile(int xOffset, int zOffset, GraphicsDevice graphicsDevice)
        {
            // Calculate position of tile from offsets
            float xPos = xOffset * TILE_WIDTH;
            float zPos = zOffset * TILE_DEPTH;

            // Create new prism to represent the tile
            tile = new RectPrism
                (
                    new Vector3(xPos, 0, zPos), 
                    TILE_DIMENSION_VECTOR,
                    TILE_COLOR,
                    graphicsDevice
                );
        }

        // Constructor to set custom color
        public LevelTile(int xOffset, int zOffset, GraphicsDevice graphicsDevice, Color color)
        {
            // Calculate position of tile from offsets
            float xPos = xOffset * TILE_WIDTH;
            float zPos = zOffset * TILE_DEPTH;

            // Create new prism to represent the tile
            tile = new RectPrism
                (
                    new Vector3(xPos, 0, zPos),
                    TILE_DIMENSION_VECTOR,
                    color,
                    graphicsDevice
                );
        }

        // Draw the tile
        public void draw(GraphicsDeviceManager graphics, Effect effect)
        {
            tile.draw(graphics, effect);
        }

        // Draw the tile
        public void draw(GraphicsDeviceManager graphics, BasicEffect effect)
        {
            tile.draw(graphics, effect);
        }

        public void dispose()
        {
            tile.dispose();
        }

        public Vector3 getPosition()
        {
            return tile.getPosition();
        }

        public RectPrism getTile()
        {
            return tile;
        }
    }

    // A Wall
    class LevelWall : QuadTreeItem
    {
        // Dimension constants
        private static readonly float WALL_WIDTH = 1.0f;
        public static readonly float WALL_HEIGHT = 4.0f;
        private static readonly float WALL_DEPTH = LevelTile.TILE_DEPTH;
        private static readonly float WALL_Y_OFFSET = WALL_HEIGHT / 2;
        private static readonly float WALL_TILE_OFFSET = (LevelTile.TILE_WIDTH - WALL_WIDTH) / 2;
        private static readonly Vector3 WALL_DIMENSION_VECTOR = new Vector3(WALL_WIDTH, WALL_HEIGHT, WALL_DEPTH);
        private static readonly Vector3 ROTATED_WALL_DIMENSION_VECTOR = new Vector3(WALL_DEPTH, WALL_HEIGHT, WALL_WIDTH);

        // Color constant
        private static readonly Color WALL_COLOR = Color.Red;

        // Visual Representation of the wall
        private RectPrism wall;

        /*=================================================================
         * CONSTRUCTOR
         * ----------------------------------------------------------------
         * Parameters:
         * - xOffset: # of tiles away from origin, along the x axis
         * - zOffset: # of tiles away from origin, along the z axis
         * - position: Character representing the positioning of the wall
         *             relative to the tile it is placed over.
         *=================================================================*/
        public LevelWall(int xOffset, int zOffset, char position, GraphicsDevice graphicsDevice)
        {
            // Calculate position of the underlying tile from offsets
            float xPos = xOffset * LevelTile.TILE_WIDTH;
            float zPos = zOffset * LevelTile.TILE_DEPTH;

            // Position and dimension vectors
            Vector3 positionVector = Vector3.Zero;
            Vector3 dimensionVector = Vector3.Zero;

            // Adjust position and dimensions, based on desired position
            switch (position)
            {
                // TOP WALL
                case '1':

                    // Set dimension
                    dimensionVector = ROTATED_WALL_DIMENSION_VECTOR;

                    // Adjust position
                    positionVector = new Vector3(xPos, WALL_Y_OFFSET, zPos - WALL_TILE_OFFSET);

                    break;

                // LEFT WALL
                case '2':

                    // Set dimension
                    dimensionVector = WALL_DIMENSION_VECTOR;

                    // Adjust position
                    positionVector = new Vector3(xPos - WALL_TILE_OFFSET, WALL_Y_OFFSET, zPos);

                    break;

                // BOTTOM WALL
                case '3':

                    // Set dimension
                    dimensionVector = ROTATED_WALL_DIMENSION_VECTOR;

                    // Adjust position
                    positionVector = new Vector3(xPos, WALL_Y_OFFSET, zPos + WALL_TILE_OFFSET);

                    break;

                // RIGHT WALL
                case '4':

                    // Set dimension
                    dimensionVector = WALL_DIMENSION_VECTOR;

                    // Adjust position
                    positionVector = new Vector3(xPos + WALL_TILE_OFFSET, WALL_Y_OFFSET, zPos);

                    break;
            }

            // Create new prism geometry to represent the wall
            wall = new RectPrism
                (
                    positionVector,
                    dimensionVector,
                    WALL_COLOR,
                    graphicsDevice
                );
        }

        // Draw the wall
        public void draw(GraphicsDeviceManager graphics, BasicEffect effect)
        {
            wall.draw(graphics, effect);
        }

        // Get bounding box
        BoundingBox QuadTreeItem.getBoundingVolume()
        {
            return wall.getBoundingBox();
        }

        // Get position
        public Vector3 getPosition()
        {
            return wall.getPosition();
        }

        // Get faces
        Plane[] QuadTreeItem.getFaces()
        {
            return wall.getFaces();
        }

        public void dispose()
        {
            wall.dispose();
        }
    }

    // A start location
    class StartTile : LevelTile
    {
        // Start tile color
        private static readonly Color START_TILE_COLOR = Color.LimeGreen;

        // CONSTRUCTOR
        public StartTile(int xOffset, int zOffset, GraphicsDevice graphicsDevice)
            : base(xOffset, zOffset, graphicsDevice, START_TILE_COLOR)
        {
        }
    }

    // A goal location
    class GoalTile : LevelTile
    {
        // Start tile color
        private static readonly Color GOAL_TILE_COLOR = Color.Violet;

        // CONSTRUCTOR
        public GoalTile(int xOffset, int zOffset, GraphicsDevice graphicsDevice)
            : base(xOffset, zOffset, graphicsDevice, GOAL_TILE_COLOR)
        {
        }
    }
}
